@using DiffPlex
@using DiffPlex.DiffBuilder
@using DiffPlex.DiffBuilder.Model

<div class="inline-diff-viewer">
    <div class="diff-header">
        <h5>@Header</h5>
    </div>
    
    <div class="diff-content">
        @if (_diffModel != null)
        {
            @foreach (var line in _diffModel.Lines)
            {
                <div class="line @GetLineClass(line.Type)">
                    <span class="line-number">@(line.Position?.ToString() ?? "")</span>
                    <span class="change-type">@GetChangeSymbol(line.Type)</span>
                    <span class="line-content">@line.Text</span>
                </div>
            }
        }
    </div>
</div>

@code {
    [Parameter] public string OldText { get; set; } = "";
    [Parameter] public string NewText { get; set; } = "";
    [Parameter] public string Header { get; set; } = "Diff";
    [Parameter] public bool IgnoreWhiteSpace { get; set; } = true;

    private DiffPaneModel? _diffModel;

    protected override void OnParametersSet()
    {
        UpdateDiff();
    }

    private void UpdateDiff()
    {
        if (!string.IsNullOrEmpty(OldText) || !string.IsNullOrEmpty(NewText))
        {
            var differ = new InlineDiffBuilder(new Differ());
            _diffModel = differ.BuildDiffModel(OldText ?? "", NewText ?? "", IgnoreWhiteSpace);
        }
    }

    private string GetLineClass(ChangeType changeType)
    {
        return changeType switch
        {
            ChangeType.Inserted => "inserted",
            ChangeType.Deleted => "deleted",
            ChangeType.Modified => "modified",
            _ => "unchanged"
        };
    }

    private string GetChangeSymbol(ChangeType changeType)
    {
        return changeType switch
        {
            ChangeType.Inserted => "+",
            ChangeType.Deleted => "-",
            ChangeType.Modified => "~",
            _ => " "
        };
    }
}

<style>
    .inline-diff-viewer {
        border: 1px solid #d0d7de;
        border-radius: 6px;
        overflow: hidden;
        font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
        font-size: 12px;
    }

    .diff-header {
        background-color: #f6f8fa;
        border-bottom: 1px solid #d0d7de;
        padding: 8px 12px;
    }

    .diff-header h5 {
        margin: 0;
        font-weight: 600;
        color: #24292f;
    }

    .diff-content {
        max-height: 500px;
        overflow: auto;
    }

    .line {
        display: flex;
        min-height: 20px;
        line-height: 20px;
        white-space: nowrap;
    }

    .line-number {
        width: 50px;
        padding: 0 8px;
        text-align: right;
        color: #656d76;
        background-color: #f6f8fa;
        border-right: 1px solid #d0d7de;
        user-select: none;
        flex-shrink: 0;
    }

    .change-type {
        width: 20px;
        padding: 0 4px;
        text-align: center;
        font-weight: bold;
        border-right: 1px solid #d0d7de;
        user-select: none;
        flex-shrink: 0;
    }

    .line-content {
        padding: 0 8px;
        white-space: pre;
        overflow-x: auto;
        flex: 1;
    }

    .line.inserted {
        background-color: #d1f4d0;
    }

    .line.inserted .line-number,
    .line.inserted .change-type {
        background-color: #a7f3d0;
        color: #0d7377;
    }

    .line.deleted {
        background-color: #ffeef0;
    }

    .line.deleted .line-number,
    .line.deleted .change-type {
        background-color: #fecdd3;
        color: #d1242f;
    }

    .line.modified {
        background-color: #fff8dc;
    }

    .line.modified .line-number,
    .line.modified .change-type {
        background-color: #fef3c7;
        color: #b45309;
    }

    .line.unchanged {
        background-color: #ffffff;
    }

    .line.unchanged .change-type {
        background-color: #f6f8fa;
    }
</style>
